package com.hudson.codec.hudson;

import com.hudson.codec.SerializableMethodEnum;
import com.hudson.codec.domain.RemotingCommand;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @Author: 渔小鲤
 * @DateTime: 2025/7/21 20:56
 **/
public class HudsonMQCodec4Binary extends ByteToMessageCodec<RemotingCommand> {
    private static final String magicStr = "Hudson";
    private static final byte[] magicBytes = magicStr.getBytes(StandardCharsets.UTF_8);
    private static final byte version = 0;
    private static final byte serializableMethod = SerializableMethodEnum.HUDSON.getSerializableMethod();

    private static final Logger logger = LoggerFactory.getLogger(HudsonMQCodec4Binary.class);

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, RemotingCommand command, ByteBuf out) throws Exception {
        logger.debug("Encoding command: {}", command);

        // 写入魔数
        out.writeBytes(magicBytes);
        // 写入版本号
        out.writeByte(version);
        // 写入序列化方式
        out.writeByte(serializableMethod);

        // 计算并写入总长度（先占位）
        int lengthIndex = out.writerIndex();
        out.writeInt(0); // 长度占位符

        // 序列化RemotingCommand
        RemotingCommand.serialize(command, out);

        // 回填长度字段
        int endIndex = out.writerIndex();
        int length = endIndex - lengthIndex - 4; // 减去长度字段本身
        out.setInt(lengthIndex, length);

        logger.debug("Encoded command with length: {}", length);
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) throws Exception {
        // 检查是否有足够的数据读取头部
        if (in.readableBytes() < 6 + 1 + 1 + 4) { // magic(6) + version(1) + serializableMethod(1) + length(4)
            return;
        }

        // 标记读取位置，便于回滚
        in.markReaderIndex();

        try {
            // 读取魔数
            byte[] magic = new byte[6];
            in.readBytes(magic);
            String magicStr = new String(magic, StandardCharsets.UTF_8);

            if (!"Hudson".equals(magicStr)) {
                throw new IllegalArgumentException("Invalid magic number: " + magicStr);
            }

            // 读取版本和序列化方式
            byte version = in.readByte();
            byte serializableMethod = in.readByte();

            // 读取长度
            int length = in.readInt();

            // 检查是否有足够的数据
            if (in.readableBytes() < length) {
                in.resetReaderIndex(); // 回滚到标记位置
                return;
            }

            // 反序列化RemotingCommand
            RemotingCommand command = RemotingCommand.deserialize(in);
            out.add(command);

            logger.debug("Decoded command: {},{},{},{},{}",
                    new String(magic, StandardCharsets.UTF_8), version, serializableMethod, length, command);

        } catch (Exception e) {
            in.resetReaderIndex(); // 出错时回滚
            throw e;
        }
    }
}
